﻿using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using StockholmsStad.Business;
using StockholmsStad.Utilities.Exceptions;
using StockholmsStad.Runtime.Serialization.DataContract;
using StockholmsStad.Runtime.Serialization.DataContract.Enums;
using StockholmsStad.ServiceModel.Interfaces;

namespace StockholmsStad.ServiceModel.Services
{
    /// <summary>
    /// Alla tjänster mot webgränssnittet
    /// </summary>
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerSession)]
    public class WebService : IWebService
    {
        #region IWebService Members

        /// <summary>
        /// Hämta ceremonispråken
        /// </summary>
        /// <returns>En lista med LanguageId och LanguageName</returns>
        public IList<ValueIdPair> GetCeremonyLanguages(User user)
        {
            try
            {
                return new CeremonyBusiness(user).GetCeremonyLanguages();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Hämta certifikatspråken
        /// </summary>
        /// <returns>En lista med LanguageId och LanguageName</returns>
        public IList<ValueIdPair> GetWeddingCertificateLanguages(User user)
        {
            try
            {
                return new CeremonyBusiness(user).GetCertificateLanguages();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Hämta hjälpmedel för ceremoni
        /// </summary>
        /// <returns>En lista med SpecialNeedId och SpecialNeedName</returns>
        public IList<ValueIdPair> GetCeremonySpecialNeeds(User user)
        {
            try
            {
                return new CeremonyBusiness(user).GetCeremonySpecialNeeds();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Hämta ceremonytyper, typ ordinarie i stadshuset och individuell på annan plats
        /// </summary>
        /// <returns>En lista med CeremonyTypeId och CeremonyTypeName</returns>
        public IList<ValueIdPair> GetCeremonyTypes(User user)
        {
            try
            {
                return new CeremonyBusiness(user).GetCeremonyTypes();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Skapar ett nytt ärende för aktuellt par och dess önskemål om ceremoni
        /// </summary>
        /// <param name="couple">Information om paret</param>
        /// <param name="ceremony">Information om ceremonin</param>
        /// <returns>Ärendenumret</returns>
        public int RegisterCouple(Couple couple, Ceremony ceremony)
        {
            try
            {
                var ticketBusiness = new TicketBusiness();
                return ticketBusiness.CreateTicket(couple, ceremony);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Uppdaterar ett ärende
        /// </summary>
        /// <param name="user"></param>
        /// <param name="couple"></param>
        /// <param name="ceremony"></param>
        /// <param name="ticketId"></param>
        public void UpdateCouple(User user, Couple couple, Ceremony ceremony, int ticketId)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                ticketBusiness.UpdateTicket(couple, ceremony, ticketId);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Sparar en bokning för ett par. Operationen kan skapa, ta bort och förändra bokning
        /// </summary>
        /// <param name="user"></param>
        /// <param name="booking"></param>
        /// <param name="ticketId"></param>
        public void SaveBooking(User user, Booking booking, int ticketId)
        {
            try
            {
                var business = new BookingBusiness(user);
                business.SaveBooking(ticketId, booking);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Implementation av operationskontraktet för avbokning av en vigsel. 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="ticketId"></param>
        /// <param name="booking"></param>
        public void CancelBooking(User user, int ticketId, Booking booking)
        {
            try
            {
                var business = new BookingBusiness(user);
                business.CancelBooking(ticketId);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Hämta bokning
        /// </summary>
        /// <param name="user"></param>
        /// <param name="ticketId"></param>
        /// <returns></returns>
        public Booking GetBooking(User user, int ticketId)
        {
            try
            {
                var business = new BookingBusiness(user);
                return business.GetBooking(ticketId);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Hämta ärendeid:t för det inloggade paret
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public int GetTicketId(User user)
        {
            try
            {
                var business = new TicketBusiness(user);
                return business.GetTicketId(user.Username);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Hämta ärende
        /// </summary>
        /// <param name="user"></param>
        /// <param name="ticketId"></param>
        /// <returns></returns>
        public Ticket GetTicket(User user, int ticketId)
        {
            try
            {
                var ticketBusiness = new TicketBusiness(user);
                return ticketBusiness.GetTicket(ticketId);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Kontrollera om bokningskod finns för en förättare
        /// </summary>
        /// <param name="user"></param>
        /// <param name="bookingCode"></param>
        /// <returns></returns>
        public bool IsBookingCodeValid(User user, string bookingCode)
        {
            try
            {
                var ministerBusiness = new MinisterBusiness(user);
                return ministerBusiness.IsBookingCodeValid(bookingCode);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        ///<summary>
        /// Kontrollerar att användaren får logga in på webben
        ///</summary>
        ///<param name="username"></param>
        ///<param name="password"></param>
        ///<returns></returns>
        public bool IsValidWebUser(string username, string password)
        {
            try
            {
                var userBusiness = new UserBusiness();
                return userBusiness.IsValidWebUser(username, password);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }
        
        /// <summary>
        /// Returns true if booking/contact info is updateable from web application
        /// </summary>
        /// <param name="booking"></param>
        /// <returns></returns>
        public bool IsUpdateable(Booking booking)
        {
            try
            {
                var bookingBusiness = new BookingBusiness();
                //Om man inte har någon bokad tid så returneras true för att man ska kunna ändra sina uppgifter samt boka tid
                return bookingBusiness.IsUpdateable(booking);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Returnerar true om användarnamnet är unikt
        /// </summary>
        /// <param name="user"></param>
        /// <param name="username"></param>
        /// <returns></returns>
        public bool IsUserNameUnique(User user, string username)
        {
            try
            {
                var userBusiness = new UserBusiness(user);
                return userBusiness.IsUserNameUnique(username);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Hämtar en användare
        /// </summary>
        /// <param name="username"></param>
        /// <returns></returns>
        public User GetUser(string username)
        {
            try
            {
                var userBusiness = new UserBusiness();
                return userBusiness.GetUser(username);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Hämtar alla bokade dagar, dvs det första tidblocket för en dag
        /// som inte har några lediga tider. Enbart dagar som ligger efter dagens datum returneras
        /// </summary>
        /// <returns></returns>
        public IEnumerable<TimeBlock> GetBookedTimeBlockDates(User user)
        {
            try
            {
                var bookingBusiness = new BookingBusiness(user);
                return bookingBusiness.GetBookedTimeBlockDates();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Hämtar alla lediga tidblock från dagens datum
        /// </summary>
        /// <returns></returns>
        public List<TimeBlock> GetFreeTimeBlockDateTimes(User user, bool ordinary)
        {
            try
            {
                var bookingBusiness = new BookingBusiness(user);
                return bookingBusiness.GetFreeTimeBlockDateTimes(true, ordinary);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        ///<summary>
        /// Hämtar alla historikloggar för användaren.
        ///</summary>
        ///<param name="user"></param>
        ///<returns></returns>
        public IList<History> GetHistoryForCurrentUser(User user)
        {
            try
            {
                if (user == null)
                    user = new User();
                return new TicketBusiness(user).GetHistoryForCurrentUser().ToList();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        ///<summary>
        /// Skickar ett mail till användaren med det befintliga lösenordet
        ///</summary>
        ///<param name="email"></param>
        public void SendForgottenPassword(string email)
        {
            try
            {
                var userBusiness = new UserBusiness();
                userBusiness.SendForgottenPasswordMail(email);
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Implementation av operationskontraktet för att hämta alla texter av en viss typ. 
        /// </summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        /// <param name="textTypeId">Id-värdet på den texttyp som ska hämtas. </param>
        /// <returns>En lista med texter. </returns>
        public IList<InformationText> GetTexts(User user, int textTypeId)
        {
            try
            {
                return new MaintenanceBusiness(user).GetTexts(textTypeId).ToList();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// DUMMY metod för att enumen InformationTextType ska genereras till klienten
        /// </summary>
        public InformationTextType GetInformationTextTypeDUMMY()
        {
            return new InformationTextType();
        }

        /// <summary>
        /// Operationskontrakt som hämtar databasens version.
        /// </summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        /// <returns>En version <see cref="StockholmsStad.Data.Entity.Version"/></returns>
        public string GetDatabaseVersion(User user)
        {
            try
            {
                return new MaintenanceBusiness(user).GetDatabaseVersion();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }

        /// <summary>
        /// Operationskontrakt som hämtar tjänstelagrets version.
        /// </summary>
        /// <param name="user">Den inloggade användaren (<see cref="User"/>).</param>
        /// <returns>Ett versionsnummer </returns>
        public string GetServiceVersion(User user)
        {
            try
            {
                return new MaintenanceBusiness(user).GetServiceVersion();
            }
            catch (StockholmStadSystemException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
            catch (StockholmStadApplicationException e)
            {
                throw new FaultException<ExceptionDetail>(new ExceptionDetail(e), e.Message);
            }
        }


        #endregion
    }
}